package com.gopay.scheduler.job;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.dps.DpsStaCode;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.AccountingPoint;
import com.gopay.common.constants.trans.PayChannel;
import com.gopay.common.constants.trans.TxnStaCode;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.dao.order.CpsGeneralMainOrderQueryDAO;
import com.gopay.common.cps.dao.wallet.prepaid.WaPrepaidOrderDtlDao;
import com.gopay.common.domain.bank.tbank.expay.Result.order;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cps.vo.CPSResponse;
import com.gopay.common.domain.cps.wallet.Wallet01200CronCommon;
import com.gopay.common.domain.dps.WaPrepaidOrderDtl;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.JsonUtils;
import com.gopay.cron.web.util.CallCPSUtil;
import com.gopay.remote.order.MainOrderField;
import com.gopay.remote.order.MainOrderUpdateRemoteService;
import com.gopay.scheduler.GopayBaseJob;

/**
 * 
 * <p>
 * Title: WalletExpressPayReturnToBankCardJob.java
 * </p>
 * <p>
 * Description:
 * 1、手机转账到银行卡交易，初审审核失败、终审失败时，已将订单金额退到2315中间户后，此定时任务会根据01605失败订单，生成一笔退款订单。
 * 2、手机信用卡还款交易，初审审核失败、终审失败时，已将订单金额退到2315中间户后，此定时任务会根据01606失败订单，生成一笔退款订单。
 * 3、充话费、充流量、充加油卡交易，欧飞返回充值失败后，已将订单金额退到2315中间户后,此定时任务会根据01611\01612\01613\失败订单，
 * 生成一笔退款订单。
 * </p>
 * <p>
 * Company: 国付宝信息科技有限公司
 * </p>
 * 
 * @author 唐阳
 * @date 2016年7月13日 下午1:18:31
 * @version V1.0
 */
public class WalletExpressPayReturnToBankCardJob extends GopayBaseJob {
	private Logger logger = LoggerFactory.getLogger(WalletExpressPayReturnToBankCardJob.class);
	@Resource(name = "cpsGeneralMainOrderQueryDAO")
	private CpsGeneralMainOrderQueryDAO cpsGeneralMainOrderQueryDAO;
	
	private MainOrderUpdateRemoteService cpsGeneralMainOrderOperClient;
	
	/**
	 * 三充业务订单
	 */
	@Resource(name = "waPrepaidOrderDtlDao")
	private WaPrepaidOrderDtlDao waPrepaidOrderDtlDao;
	
	@Resource(name = "cpsGeneralMainOrderOperClient")
	public void setCpsGeneralMainOrderOperClient(MainOrderUpdateRemoteService cpsGeneralMainOrderOperClient) {
		this.cpsGeneralMainOrderOperClient = cpsGeneralMainOrderOperClient;
	}
	@Override
	protected void doJobInternal() {
		// TODO Auto-generated method stub
		// 1、查询初审审核失败或终审失败的手机转账到银行卡交易、初审审核失败或终审失败的手机信用卡还款交易、充值失败的三充交易
		logger.info("创建退款订单begin");
		List mainOrderList = queryMainOrderForReturnToBank();
		if(mainOrderList!=null && mainOrderList.size()>0){
			for(int i = 0 ;i < mainOrderList.size() ;i++){
				String gopayOrderId = (String) mainOrderList.get(i);
				CpsGenMainOrder cpsGenMainOrder = cpsGeneralMainOrderQueryDAO.find(CpsGenMainOrder.class, gopayOrderId);
				logger.info(i + "、交易订单信息cpsGenMainOrder为：" + cpsGenMainOrder);
				//add by leixiaobao 如果是三充的交易去查询三充业务订单
				WaPrepaidOrderDtl pOrderDtl = null;
				if( IntTxnCd._01611.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
					|| IntTxnCd._01612.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
					|| IntTxnCd._01613.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
					|| IntTxnCd._01618.value.equals(cpsGenMainOrder.getGopayIntTxnCd()) ){
					pOrderDtl = waPrepaidOrderDtlDao.find(WaPrepaidOrderDtl.class, gopayOrderId);
				}
				
				logger.info(i + "、交易订单信息WaPrepaidOrderDtl为：" + pOrderDtl);
				CPSResponse response = null;
				if(checkOglOrder(cpsGenMainOrder, pOrderDtl)){
					try {
						Map<MainOrderField, String> values = new HashMap<MainOrderField, String>();
						//add by leixiaobao 老三充交易执行原流程
						if( pOrderDtl != null ){
							//2、退款前，将订单状态置为90504，避免订单处理过程中，被其他任务处理
							logger.info("before-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + pOrderDtl.getRechargeStatus());
							pOrderDtl.setRechargeStatus(DpsStaCode.DPS_STA_CD_90504.value);
							pOrderDtl.setUpdateTs(new Date());
							waPrepaidOrderDtlDao.update(pOrderDtl);
							logger.info("after-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + TxnStaCode.TXN_STA_CD_90504.value );
						}else{
							//2、退款前，将订单状态置为90504，避免订单处理过程中，被其他任务处理
							logger.info("before-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + cpsGenMainOrder.getTxnStaCd());
							values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_90504.value+"");
							cpsGeneralMainOrderOperClient.updateMany(gopayOrderId,cpsGenMainOrder.getVersion()+"", values);
							logger.info("after-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + TxnStaCode.TXN_STA_CD_90504.value );
						}

						// 3、生成退款订单
						response = createExpressPayReturnOrder(cpsGenMainOrder.getGopayOrderId());
						
						if (ProcCodeConstants.PROC_CODE_100S1000.equals(response.getRespCode())) {//创建退款订单成功
							//4、更新原手机转账到银行卡交易、手机信用卡还款交易、三充交易的交易状态为20002
							cpsGenMainOrder = cpsGeneralMainOrderQueryDAO.find(CpsGenMainOrder.class, gopayOrderId);
							logger.info("before-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + cpsGenMainOrder.getTxnStaCd());
							values = new HashMap<MainOrderField, String>();
							String s = DateUtils.getCurrDate();
							values.put(MainOrderField.TRAN_FINISH_TIME, s);
							values.put(MainOrderField.ORDER_STLM_TIME, s);
							if(IntTxnCd._01611.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
									||IntTxnCd._01612.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
									||IntTxnCd._01613.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
									|| IntTxnCd._01618.value.equals(cpsGenMainOrder.getGopayIntTxnCd()) ){//三充交易生成退款订单后，状态改为90502，
								if( pOrderDtl != null ){
									pOrderDtl.setRechargeStatus(DpsStaCode.DPS_STA_CD_90502.value);
									pOrderDtl.setUpdateTs(new Date());
								}else{
									values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_90502.value+"");
								}
							}else if(IntTxnCd._01605.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
									||IntTxnCd._01606.value.equals(cpsGenMainOrder.getGopayIntTxnCd())){//手机转账到银行卡、信用卡还款生成退款订单后，状态改为20002
								values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_20002.value+"");
							}else{
								throw new GopayException("订单类型错误,订单类型:" + cpsGenMainOrder.getGopayIntTxnCd());
							}
							//add by leixiaobao 2017-5-17 如果扫描到数据来源三充业务订单，那么更新业务订单状态，不更新主订单状态
							if( pOrderDtl != null ){
								waPrepaidOrderDtlDao.update(pOrderDtl);
							}else{
								cpsGeneralMainOrderOperClient.updateMany(gopayOrderId,cpsGenMainOrder.getVersion()+"" ,values);
							}
							logger.info("after-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + TxnStaCode.TXN_STA_CD_20002.value );
						}else{
							//生成退款订单失败，将状态更新为90503或20003，等待下次定时任务
							cpsGenMainOrder = cpsGeneralMainOrderQueryDAO.find(CpsGenMainOrder.class, gopayOrderId);
							logger.info("before-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + cpsGenMainOrder.getTxnStaCd());
							values = new HashMap<MainOrderField, String>();
							//01605/01606更新成20003 modify by tangyang at 20170329
							if(StringUtils.equals(IntTxnCd._01605.value, cpsGenMainOrder.getGopayIntTxnCd())
							        ||StringUtils.equals(IntTxnCd._01606.value, cpsGenMainOrder.getGopayIntTxnCd())){
							    values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_20003.value+"");
							}
							else if(StringUtils.equals(IntTxnCd._01611.value, cpsGenMainOrder.getGopayIntTxnCd())
							        ||StringUtils.equals(IntTxnCd._01612.value, cpsGenMainOrder.getGopayIntTxnCd())
							        ||StringUtils.equals(IntTxnCd._01613.value, cpsGenMainOrder.getGopayIntTxnCd())
							        || StringUtils.equals(IntTxnCd._01618.value, cpsGenMainOrder.getGopayIntTxnCd()) ){
								if( pOrderDtl != null ){
									pOrderDtl.setRechargeStatus(DpsStaCode.DPS_STA_CD_90503.value);
									pOrderDtl.setUpdateTs(new Date());
								}else{
									values.put(MainOrderField.TXN_STA_CD, TxnStaCode.TXN_STA_CD_90503.value+"");
								}
							}
							//add by leixiaobao 2017-5-17 如果扫描到数据来源三充业务订单，那么更新业务订单状态，不更新主订单状态
							if( pOrderDtl != null ){
								waPrepaidOrderDtlDao.update(pOrderDtl);
							}else{
								cpsGeneralMainOrderOperClient.updateMany(gopayOrderId,cpsGenMainOrder.getVersion()+"", values);
							}
							logger.info("after-更新订单状态gopayOrderId=" + cpsGenMainOrder.getGopayOrderId() + ",txnStaCd=" + cpsGenMainOrder.getTxnStaCd());
						}
					} catch (GopayException e) {
						logger.error("GopayException自动退款更新订单失败,gopayOrderId:" + gopayOrderId, e);
						logger.error(e.getMessage());
					} catch (Exception e) {
						logger.error("Exception自动退款更新订单失败,gopayOrderId:" + gopayOrderId ,e);
						logger.error(e.getMessage());
					}
				}
			}
		}
		logger.info("创建退款订单end");
	}

	/**
	 * 
	 * <p>
	 * Description: 1、查询手机转账到银行卡初审、终审失败的的快捷支付交易：交易类型01605，订单状态为，付款通道为03或06
	 * 2、查询手机转账到银行卡初审、终审失败的的快捷支付交易：交易类型01606，订单状态为，付款通道为03或06
	 * 3、查询欧飞返回失败的三充交易的借记卡或行用卡快捷支付交易：类型01611、01612、01613，订单状态为90502，付款通道为03或06
	 * </p>
	 * 
	 * @author 唐阳
	 * @date 2016年7月13日 下午2:00:18
	 * @version V1.0
	 *
	 * @return 符合条件的主订单
	 * @throws IOException 
	 * @throws JsonMappingException 
	 * @throws JsonGenerationException 
	 */
	private List queryMainOrderForReturnToBank() {
		StringBuffer sql = new StringBuffer();
		// 查询手机转账到银行卡初审、终审失败的的快捷支付交易：交易类型01605，订单状态为20003，付款通道为03或06
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
				+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01605 "
				+ " and m.txn_sta_cd=:txnStaCd01605 "
				+ " and m.pay_channel=:payChannel01605 "
				+ " and m.accounting_point=:accountingPoint01605 ");//增加对01605记账点的过滤，清结算出款审批拒绝时记账点为12,风控同一卡号同一金额的20003的订单记账点为空
		sql.append(" union all ");
		// 查询手机转账到银行卡初审、终审失败的的快捷支付交易：交易类型01606，订单状态为20003，付款通道为03或06
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
				+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01606 "
				+ " and m.txn_sta_cd=:txnStaCd01606 "
				+ " and m.pay_channel=:payChannel01606 "
				+ " and m.accounting_point=:accountingPoint01606 ");//增加对01606记账点的过滤，清结算出款审批拒绝时记账点为12,风控同一卡号同一金额的20003的订单记账点为空
		sql.append(" union all ");
		// 查询欧飞返回失败的充话费交易的借记卡或行用卡快捷支付交易：类型01611，订单状态为90502，付款通道为03或06
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
				+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01611 "
				+ " and m.txn_sta_cd=:txnStaCd01611 ");
//				+ " and ( m.pay_channel=:payChannel016111 or m.pay_channel=:payChannel016112 ) ");
		sql.append(" union all ");
		//查询三充业务订单，状态为90503订单
		sql.append(
				" select m.gopay_order_id from wa_prepaid_order_dtl m "
				+ " where m.RECHARGE_STATUS=:rechargeStatus ");
		sql.append(" union all ");
		// 查询欧飞返回失败的充流量交易的借记卡或行用卡快捷支付交易：类型01612，订单状态为90502，付款通道为03或06
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
				+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01612 "
				+ " and m.txn_sta_cd=:txnStaCd01612 ");
//				+ " and ( m.pay_channel=:payChannel016121 or m.pay_channel=:payChannel016122 ) ");
		sql.append(" union all ");
		// 查询欧飞返回失败的充加油卡交易的借记卡或行用卡快捷支付交易：类型01613，订单状态为90502，付款通道为03或06
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
				+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01613 "
				+ " and m.txn_sta_cd=:txnStaCd01613 ");
//				+ " and ( m.pay_channel=:payChannel016131 or m.pay_channel=:payChannel016132 ) ");
		sql.append(" union all ");
		// 查询欧飞返回失败的视频会员充值交易的借记卡或行用卡快捷支付交易：类型01618，订单状态为90503，付款通道为03,06,02
		sql.append(
				" select m.gopay_order_id from cps_gen_main_order m "
						+ " where m.gopay_int_txn_cd=:gopayIntTxnCd01618 "
						+ " and m.txn_sta_cd=:txnStaCd01618 ");

		Map<String, Object> param = new HashMap<String, Object>();
		// 手机转账到银行卡交易查询条件
		param.put("gopayIntTxnCd01605", IntTxnCd._01605.value);
		param.put("txnStaCd01605", "20003");
		param.put("payChannel01605", PayChannel._03.value);
		param.put("accountingPoint01605", AccountingPoint._01605_AUDIT_REFUSE.value);
		// 手机信用卡还款交易查询条件
		param.put("gopayIntTxnCd01606", IntTxnCd._01606.value);
		param.put("txnStaCd01606", "20003");
		param.put("payChannel01606", PayChannel._03.value);
		param.put("accountingPoint01606", AccountingPoint._01606_AUDIT_REFUSE.value);
		// 充话费交易查询条件
		param.put("gopayIntTxnCd01611", IntTxnCd._01611.value);
		param.put("txnStaCd01611", "90503");
//		param.put("payChannel016111", PayChannel._03.value);
//		param.put("payChannel016112", PayChannel._06.value);
		// 充流量交易查询条件
		param.put("gopayIntTxnCd01612", IntTxnCd._01612.value);
		param.put("txnStaCd01612", "90503");
//		param.put("payChannel016121", PayChannel._03.value);
//		param.put("payChannel016122", PayChannel._06.value);
		// 充加油卡交易查询条件
		param.put("gopayIntTxnCd01613", IntTxnCd._01613.value);
		param.put("txnStaCd01613", "90503");
//		param.put("payChannel016131", PayChannel._03.value);
//		param.put("payChannel016132", PayChannel._06.value);

		//视频会员充值
		param.put("gopayIntTxnCd01618", IntTxnCd._01618.value);
		param.put("txnStaCd01618", "90503");
		
		param.put("rechargeStatus", "90503");
		List mainOrderIdList = cpsGeneralMainOrderQueryDAO.findBySql(sql.toString(), param);
		try {
			logger.info("需要退款的订单为：" + JsonUtils.toJson(mainOrderIdList));
		} catch (JsonGenerationException e) {
			logger.error("打印需要退款的订单错误", e);
		} catch (JsonMappingException e) {
			logger.error("打印需要退款的订单错误", e);
		} catch (IOException e) {
			logger.error("打印需要退款的订单错误", e);
		}
		return mainOrderIdList;
	}

	private boolean checkOglOrder(CpsGenMainOrder cpsGenMainOrder, WaPrepaidOrderDtl pOrderDtl) {
		if (cpsGenMainOrder == null){
			logger.error("交易定单订单异常，订单不存在");
			return false;
		}
		//校验订单状态
		if(IntTxnCd._01605.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
				&& TxnStaCode.TXN_STA_CD_20003.value != cpsGenMainOrder.getTxnStaCd()){
			//手机转账到银行交易，订单状态必须是20003，才能发起退款交易
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			return false;
		}else if(IntTxnCd._01606.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
				&& TxnStaCode.TXN_STA_CD_20003.value != cpsGenMainOrder.getTxnStaCd()){
			//手机转账到银行交易，订单状态必须是20003，才能发起退款交易
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			return false;
		}else if(IntTxnCd._01611.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
				&& TxnStaCode.TXN_STA_CD_90503.value != cpsGenMainOrder.getTxnStaCd()){
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			if( pOrderDtl != null && TxnStaCode.TXN_STA_CD_90503.value == pOrderDtl.getRechargeStatus() ){
				return true;
			}
			return false;
		}else if(IntTxnCd._01612.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
				&& TxnStaCode.TXN_STA_CD_90503.value != cpsGenMainOrder.getTxnStaCd()){
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			if( pOrderDtl != null && TxnStaCode.TXN_STA_CD_90503.value == pOrderDtl.getRechargeStatus() ){
				return true;
			}
			return false;
		}else if(IntTxnCd._01613.value.equals(cpsGenMainOrder.getGopayIntTxnCd())
				&& TxnStaCode.TXN_STA_CD_90503.value != cpsGenMainOrder.getTxnStaCd()){
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			if( pOrderDtl != null && TxnStaCode.TXN_STA_CD_90503.value == pOrderDtl.getRechargeStatus() ){
				return true;
			}
			return false;
		}else if ( IntTxnCd._01618.value.equals(cpsGenMainOrder.getGopayIntTxnCd()) 
				&& TxnStaCode.TXN_STA_CD_90503.value != cpsGenMainOrder.getTxnStaCd() ){
			logger.error("交易定单订单异常，gopayOrderId="+ cpsGenMainOrder.getGopayOrderId());
			if( pOrderDtl != null && TxnStaCode.TXN_STA_CD_90503.value == pOrderDtl.getRechargeStatus() ){
				return true;
			}
		}
		return true;
	}
	
	/**
	 * 
	 * <p>Description: 根据原交易订单号，创建退款订单</p>
	 * @author 唐阳
	 * @date 2016年7月13日 下午6:59:44
	 * @version V1.0 
	 *
	 * @return
	 * @throws GopayException 
	 */
	private CPSResponse createExpressPayReturnOrder(String gopayOrderId) throws GopayException{
		// 调用CPS
		Wallet01200CronCommon tranVo = new Wallet01200CronCommon();
		tranVo.setOglGopayOrderId(gopayOrderId);
        CPSResponse response = null;
        try {
            // 调用cps
             response = CallCPSUtil.callByVOTicket(tranVo);
             logger.info("创建退款订单结果：" +JsonUtils.toJson(response));
        }catch (JsonGenerationException e) {
			logger.error("打印需要退款的订单错误", e);
		} catch (JsonMappingException e) {
			logger.error("打印需要退款的订单错误", e);
		} catch (IOException e) {
			logger.error("打印需要退款的订单错误", e);
		}
        return response;
	}
	
}
